home *** CD-ROM | disk | FTP | other *** search
/ CD World Haziran 1997 / CD World Haziran 1997.iso / Cesitlemeler / Directx 3.0 / dx3.exe / SDK / SAMPLES / DUEL / DUEL.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-04  |  15.6 KB  |  621 lines

  1. /*==========================================================================
  2.  *
  3.  *  Copyright (C) 1995-1996 Microsoft Corporation. All Rights Reserved.
  4.  *
  5.  *  File:       duel.c
  6.  *  Content:    Multi-player duel
  7.  *
  8.  *
  9.  ***************************************************************************/
  10. #define INITGUID
  11. #include "duel.h"
  12. #include "gameproc.h"
  13. #include "gfx.h"
  14. #include "comm.h"
  15. #include "input.h"
  16. #include "lobby.h"
  17. #include "wizard.h"
  18. #include "util.h"
  19. #include "sfx.h"
  20.  
  21. // {33925241-05F8-11d0-8063-00A0C90AE891}
  22. DEFINE_GUID(DUEL_GUID, 
  23. 0x33925241, 0x5f8, 0x11d0, 0x80, 0x63, 0x0, 0xa0, 0xc9, 0xa, 0xe8, 0x91);
  24.  
  25. /*
  26.  * Externals
  27.  */
  28. extern DWORD            gdwFrameCount;
  29. extern DWORD            gdwFrameTime;
  30. extern int              gnProgramState;
  31. extern SHIP             gOurShip;
  32. extern LPDPLCONNECTION  glpdplConnection;
  33. extern DPID             gOurID;
  34. extern BOOL             gbNoField;
  35.  
  36.  
  37. /*
  38.  * Globals
  39.  */
  40. LPGUID                  glpGuid;                // Duel's GUID
  41. HWND                    ghWndMain;              // Main application window handle
  42. HINSTANCE               ghinst;                 // Application instance handle      
  43. BOOL                    gbShowFrameCount=TRUE;  // Show FPS ?
  44. BOOL                    gbIsActive;             // Is the application active ?
  45. BOOL                    gbUseEmulation;         // DDHEL or DDHAL for Graphics
  46. BOOL                    gbIsHost;               // Are we hosting or joining a game     
  47. DWORD                   gdwKeys;                // User keyboard input
  48. DWORD                   gdwOldKeys;             // Last frame's keyboard input
  49. BOOL                    gbFullscreen=FALSE;     // Window or FullScreen mode ?
  50. RECT                    grcWindow;              // client rectangle of main window
  51. HANDLE                  ghThread;               // handle to wizard thread
  52. TCHAR                   gtszClassName[MAX_CLASSNAME]; // Duel's class name  
  53. BOOL                    gbReliable;             // sends are reliable
  54.  
  55. /*
  56.  * Statics
  57.  */
  58. static BOOL             gbReinitialize;         // used for switching display modes
  59.  
  60. /*
  61.  * WinMain
  62.  */
  63. int WINAPI WinMain( HINSTANCE hinstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
  64.                         int nCmdShow )
  65. {
  66.     BOOL bHelp=FALSE;
  67.     MSG     msg;
  68.  
  69.     ghinst = hinstance;
  70.  
  71.     // Parse command line
  72.     while( lpCmdLine[0] == '-' )
  73.     {
  74.         lpCmdLine++;
  75.  
  76.         switch (*lpCmdLine++)
  77.         {
  78.         case 'e':
  79.             gbUseEmulation = TRUE;
  80.             break;
  81.         case 'd':
  82.             gbNoField = TRUE;
  83.             break;
  84.         case '?':
  85.         default:
  86.             bHelp= TRUE;
  87.             gbFullscreen= FALSE;  // give help in windowed mode
  88.             break;
  89.         }
  90.  
  91.         while( isspace(*lpCmdLine) )
  92.         {
  93.             lpCmdLine++;
  94.         }
  95.     }
  96.  
  97.     /*
  98.      * Give user help if asked for
  99.      */
  100.  
  101.     if( bHelp )
  102.     {
  103.         TCHAR tszHelpMsg[MAX_HELPMSG];
  104.         TCHAR tszTitle[MAX_WINDOWTITLE];
  105.  
  106.         LoadString(ghinst, IDS_DUEL_HELP, tszHelpMsg, MAX_HELPMSG);
  107.         LoadString(ghinst, IDS_DUEL_TITLE, tszTitle, MAX_WINDOWTITLE);
  108.         MessageBox(ghWndMain, tszHelpMsg, tszTitle, MB_OK );
  109.         return TRUE;
  110.     }
  111.  
  112.  
  113.     if( !InitApplication(hinstance) )
  114.     {
  115.         return FALSE;
  116.     }
  117.  
  118.     // were we launched by a lobby ?
  119.     if (LaunchedByLobby())
  120.     {
  121.         // start game
  122.         PostMessage(ghWndMain, UM_LAUNCH, 0, 0);
  123.         gbIsActive = TRUE;
  124.     }
  125.  
  126.     gdwFrameTime = timeGetTime();
  127.  
  128.     while( TRUE )
  129.     {
  130.         if (gbIsActive)
  131.         {
  132.             // any windows messages ? (returns immediately)
  133.             if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
  134.             {
  135.                 if( !GetMessage( &msg, NULL, 0, 0 ) )
  136.                 {
  137.                     return msg.wParam;
  138.                 }
  139.                 TranslateMessage(&msg);
  140.                 DispatchMessage(&msg);
  141.             }
  142.             else
  143.             {
  144.                 // Poll our receive queue. Polling is used in the sample only for simplicity.
  145.                 // Receiving messages using an event is the recommended way.
  146.                 if (gnProgramState != PS_SPLASH)
  147.                 {
  148.                     ReceiveMessages();
  149.                 }
  150.  
  151.                 // update screen
  152.                 if (!UpdateFrame())
  153.                 {
  154.                     ExitGame();
  155.                 }
  156.             }
  157.         }
  158.         else
  159.         {
  160.             // any windows messages ? (blocks until a message arrives)
  161.             if( !GetMessage( &msg, NULL, 0, 0 ) )
  162.             {
  163.                 return msg.wParam;
  164.             }
  165.             TranslateMessage(&msg);
  166.             DispatchMessage(&msg);
  167.         }
  168.     }
  169. } /* WinMain */
  170.  
  171.  
  172. /*
  173.  * MainWndproc
  174.  *
  175.  * Callback for all Windows messages
  176.  */
  177. long WINAPI MainWndproc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
  178. {
  179.     PAINTSTRUCT ps;
  180.     HDC         hdc;
  181.     DWORD dwRetCode;
  182.     DWORD dwTid;
  183.  
  184.     switch( message )
  185.     {
  186.     case WM_SIZE:
  187.     case WM_MOVE:
  188.         // get the client rectangle
  189.         if (gbFullscreen)
  190.         {
  191.             SetRect(&grcWindow, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
  192.         }
  193.         else
  194.         {
  195.             GetClientRect(hWnd, &grcWindow);
  196.             ClientToScreen(hWnd, (LPPOINT)&grcWindow);
  197.             ClientToScreen(hWnd, (LPPOINT)&grcWindow+1);
  198.         }
  199.         break;
  200.  
  201.     case WM_ACTIVATE:
  202.         // ignore this message during reinitializing graphics
  203.         if (gbReinitialize) return 0;
  204.  
  205.         // When we are deactivated, although we don't update our screen, we still need to
  206.         // to empty our receive queue periodically as messages will pile up otherwise. 
  207.         // Polling the receive queue continuously even when we are deactivated causes our app
  208.         // to consume all the CPU time. To avoid hogging the CPU, we block on GetMessage() WIN API
  209.         // and setup a timer to wake ourselves up at regular intervals to process our messages.
  210.  
  211.         if (LOWORD(wParam) == WA_INACTIVE)
  212.         {
  213.             // deactivated
  214.             gbIsActive = FALSE;
  215.             if (PS_ACTIVE == gnProgramState)
  216.             {
  217.                 SetTimer(hWnd, RECEIVE_TIMER_ID, RECEIVE_TIMEOUT, NULL);
  218.             }
  219.         }
  220.         else
  221.         {
  222.             // activated
  223.             gbIsActive = TRUE;
  224.             if (PS_ACTIVE == gnProgramState)
  225.             {
  226.                 KillTimer(hWnd, RECEIVE_TIMER_ID);
  227.             }
  228.         }
  229.  
  230.         // set game palette, if activated in game mode
  231.         if (gbIsActive && (gnProgramState != PS_SPLASH))
  232.             SetGamePalette();
  233.  
  234.         ReacquireInputDevices();
  235.  
  236.         return 0;
  237.  
  238.     case WM_CREATE:
  239.         break;
  240.  
  241.     case WM_SYSKEYUP:
  242.         switch( wParam )
  243.         {
  244.         // handle ALT+ENTER (fullscreen/window mode)
  245.         case VK_RETURN:
  246.             // mode switch is allowed only during the game
  247.             if (gnProgramState == PS_ACTIVE)
  248.             {
  249.                 gbReinitialize = TRUE;
  250.                 ReleaseLocalData();  //only sound buffers have to be rels'd anyway.
  251.                 CleanupSfx();
  252.                 CleanupInput();
  253.                 CleanupGraphics();
  254.                 DestroyWindow(ghWndMain);
  255.                 gbFullscreen = !gbFullscreen;
  256.                 InitGraphics();
  257.                 InitInput();
  258.                 InitSfx();
  259.                 InitLocalSoundData();
  260.                 gbReinitialize = FALSE;
  261.             }
  262.             break;
  263.         }
  264.         break;
  265.  
  266.     case WM_KEYDOWN:
  267.         switch( wParam )
  268.         {
  269.         case 'r':
  270.         case 'R':
  271.             // toggle reliable status
  272.             gbReliable = !gbReliable;
  273.             UpdateTitle();
  274.             break;
  275.  
  276.         case VK_F1:
  277.             {
  278.                 TCHAR tszHelpMsg[MAX_HELPMSG];
  279.                 TCHAR tszTitle[MAX_WINDOWTITLE];
  280.  
  281.                 LoadString(ghinst, IDS_DUEL_HELP, tszHelpMsg, MAX_HELPMSG);
  282.                 LoadString(ghinst, IDS_DUEL_TITLE, tszTitle, MAX_WINDOWTITLE);
  283.                 MessageBox(ghWndMain, tszHelpMsg, tszTitle, MB_OK );
  284.             }
  285.             break;
  286.  
  287.         case VK_F5:
  288.             gbShowFrameCount = !gbShowFrameCount;
  289.             if( gbShowFrameCount )
  290.             {
  291.                 gdwFrameCount = 0;
  292.                 gdwFrameTime = timeGetTime();
  293.             }
  294.             break;
  295.  
  296.         case VK_RETURN:
  297.             if( (gnProgramState == PS_SPLASH) && !gbFullscreen)
  298.             {
  299.                 // get connection settings from user
  300.                 ghThread = CreateThread(NULL, 0, (LPVOID)DoWizard, 0, 0, &dwTid);
  301.             }
  302.             break;
  303.  
  304.         case VK_ESCAPE:
  305.         case VK_F12:
  306.             // adios
  307.             ExitGame();
  308.             return 0;
  309.         }
  310.         break;
  311.  
  312.     case WM_ERASEBKGND:
  313.         return 1;
  314.  
  315.     case WM_PAINT:
  316.         hdc = BeginPaint( hWnd, &ps );
  317.         if (gnProgramState == PS_SPLASH)
  318.         {
  319.             // display the splash screen
  320.             bltSplash(NULL);
  321.         }
  322.  
  323.         EndPaint( hWnd, &ps );
  324.         return 1;
  325.  
  326.     case UM_LAUNCH:
  327.         // cleanup the wizard thread
  328.         if (ghThread)
  329.         {
  330.             // wait for thread to exit
  331.             while (!GetExitCodeThread(ghThread, &dwRetCode));
  332.             CloseHandle(ghThread);
  333.         }
  334.         
  335.         // start the game in rest mode
  336.         gnProgramState = PS_REST;
  337.         LaunchGame();
  338.         return 1;
  339.  
  340.     case UM_ABORT:
  341.         // cleanup the wizard thread
  342.         if (ghThread)
  343.         {
  344.             // wait for thread to exit
  345.             while (!GetExitCodeThread(ghThread, &dwRetCode));
  346.             CloseHandle(ghThread);
  347.         }
  348.         ExitGame();
  349.         return 1;
  350.  
  351.     case WM_TIMER:
  352.         ReceiveMessages();
  353.         break;
  354.  
  355.     case WM_DESTROY:
  356.         // if gbReinitialize is TRUE don't quit, we are just switching display modes
  357.         if (!gbReinitialize)
  358.         {
  359.             CleanupApplication();
  360.             PostQuitMessage( 0 );
  361.         }
  362.         return 0;
  363.  
  364.     default:
  365.         break;
  366.     }
  367.     return DefWindowProc(hWnd, message, wParam, lParam);
  368.  
  369. } /* MainWndproc */
  370.  
  371. /*
  372.  * InitApplication
  373.  *
  374.  * Do that initialization stuff...
  375.  */
  376. BOOL InitApplication( HINSTANCE hinst )
  377. {
  378.     WNDCLASS    wc;
  379.     BOOL        rc;
  380.  
  381.     glpGuid = (LPGUID) &DUEL_GUID;
  382.  
  383.     LoadString(ghinst, IDS_DUEL_CLASSNAME, gtszClassName, MAX_CLASSNAME);
  384.  
  385.     wc.style = CS_DBLCLKS;
  386.     wc.lpfnWndProc = MainWndproc;
  387.     wc.cbClsExtra = 0;
  388.     wc.cbWndExtra = 0;
  389.     wc.hInstance = hinst;
  390.     wc.hIcon = LoadIcon( hinst, MAKEINTRESOURCE(DUEL_ICON));
  391.     wc.hCursor = LoadCursor( NULL, IDC_ARROW );
  392.     wc.hbrBackground = GetStockObject( BLACK_BRUSH );
  393.     wc.lpszMenuName =  NULL;
  394.     wc.lpszClassName = gtszClassName;
  395.     rc = RegisterClass( &wc );
  396.     if( !rc )
  397.     {
  398.         return FALSE;
  399.     }
  400.  
  401.     // Initialize all components
  402.     if ((!InitGraphics()) || (!InitInput()) || (!InitSfx()))
  403.     {
  404.         return FALSE;
  405.     }
  406.  
  407.     // start in splash mode
  408.     gnProgramState = PS_SPLASH;
  409.  
  410.     return TRUE;
  411.  
  412. } /* initApplication */
  413.  
  414. /*
  415.  * CleanupApplication
  416.  *
  417.  * Calls clean up on all components
  418.  */
  419. void CleanupApplication( void )
  420. {
  421.     CleanupComm();
  422.     CleanupSfx();
  423.     CleanupGraphics();
  424.     CleanupInput();
  425. }
  426.  
  427. /*
  428.  * LaunchedByLobby
  429.  *
  430.  * Determines if we were launched by a lobby. If so, gets the connection settings
  431.  * and creates our player using the information from the lobby
  432.  */
  433. BOOL LaunchedByLobby(void)
  434. {
  435.     HRESULT hr;
  436.     HWND    hwndStatus;
  437.  
  438.     // create a lobby object
  439.     hr = DPLobbyCreate();
  440.     if (FAILED(hr))
  441.     {
  442.         ShowError(IDS_DPLOBBY_ERROR_C);
  443.         return FALSE;
  444.     }
  445.  
  446.     // get connection settings from the lobby (into glpdplConnection)
  447.     hr = DPLobbyGetConnectionSettings();
  448.     if (FAILED(hr))
  449.     {
  450.         if (DPERR_NOTLOBBIED == hr)
  451.         {
  452.             // we were not lobbied - start up game normally
  453.             hr = DPLobbyRelease();
  454.             if (FAILED(hr))
  455.             {
  456.                 ShowError(IDS_DPLOBBY_ERROR_R);
  457.                 goto FAIL;
  458.             }
  459.             // move on
  460.             return FALSE;
  461.         }
  462.         else
  463.         {
  464.             ShowError(IDS_DPLOBBY_ERROR_GCS);
  465.             goto FAIL;
  466.         }
  467.     }
  468.  
  469.     // are we hosting or joining ?
  470.     if (glpdplConnection->dwFlags & DPLCONNECTION_CREATESESSION)
  471.     {
  472.         gbIsHost = TRUE;
  473.     }
  474.  
  475.     // set our session flags
  476.     glpdplConnection->lpSessionDesc->dwFlags = DPSESSION_MIGRATEHOST | 
  477.                                                  DPSESSION_KEEPALIVE;
  478.  
  479.     // let lobby know our connection flags
  480.     hr = DPLobbySetConnectionSettings();
  481.     if (FAILED(hr))
  482.     {
  483.         ShowError(IDS_DPLOBBY_ERROR_SCS);
  484.         goto FAIL;
  485.     }
  486.  
  487.     if ( !gbIsHost ) 
  488.     {
  489.         // show splash screen and 
  490.         // connection status if we are joining a game
  491.         UpdateWindow(ghWndMain);
  492.         hwndStatus = ShowConnectStatus();
  493.     }
  494.     else
  495.     {
  496.         // we are hosting, don't need connection status
  497.         hwndStatus = NULL;
  498.     }
  499.  
  500.     // connect to the lobby
  501.     hr = DPLobbyConnect();
  502.  
  503.     if ( hwndStatus )
  504.     {
  505.         // get rid of the connectino status window
  506.         DestroyWindow(hwndStatus);
  507.     }
  508.  
  509.     if (FAILED(hr))
  510.     {
  511.         ShowError(IDS_DPLOBBY_ERROR_CONNECT);
  512.         goto FAIL;
  513.     }
  514.  
  515.     // create our player
  516.     hr = DPlayCreatePlayer(
  517.                             &gOurID,
  518. #ifdef UNICODE
  519.                             glpdplConnection->lpPlayerName->lpszShortName,
  520. #else
  521.                             glpdplConnection->lpPlayerName->lpszShortNameA,
  522. #endif
  523.                             NULL,
  524.                             NULL,
  525.                             0
  526.                           );
  527.  
  528.     if (FAILED(hr))
  529.     {
  530.         ShowError(IDS_DPLAY_ERROR_CP);
  531.         goto FAIL;
  532.     }
  533.  
  534.  
  535.     // cleanup
  536.     hr = DPLobbyRelease();
  537.     if (FAILED(hr))
  538.     {
  539.         ShowError(IDS_DPLOBBY_ERROR_R);
  540.         goto FAIL;
  541.     }
  542.  
  543.     // we were lobbied
  544.     return TRUE;
  545.  
  546. FAIL:
  547.     // cleanup and exit
  548.     DPLobbyRelease();
  549.     ExitGame();
  550.     return FALSE;
  551. }
  552.  
  553. /*
  554.  * Displays error to the user
  555.  */
  556. BOOL ShowError( int iStrID )
  557. {
  558.     TCHAR tszMsg[MAX_ERRORMSG];
  559.     TCHAR tszTitle[MAX_WINDOWTITLE];
  560.  
  561.     LoadString(ghinst, iStrID, tszMsg, MAX_ERRORMSG);
  562.     LoadString(ghinst, IDS_DUEL_ERROR_TITLE, tszTitle, MAX_WINDOWTITLE);
  563.     MessageBox( ghWndMain, tszMsg, tszTitle, MB_OK );
  564.     return FALSE;
  565. }
  566.  
  567. /*
  568.  * Displays connection status to the user
  569.  */
  570. HWND ShowConnectStatus(void)
  571. {
  572.     HWND hwnd;
  573.  
  574.     hwnd = CreateDialog( ghinst, MAKEINTRESOURCE(IDD_CONNECT_STATUS), ghWndMain, NULL);
  575.  
  576.     return hwnd;
  577.  
  578. }
  579.  
  580. /*
  581.  * UpdateTitle
  582.  *
  583.  * Updates the window title based on application status
  584.  */
  585. void UpdateTitle(void)
  586. {
  587.     DWORD dwFeatures;
  588.     TCHAR tszTitle[MAX_WINDOWTITLE];
  589.     UINT iStringID;
  590.  
  591.     // calculate title features
  592.     dwFeatures = 0;
  593.     if (gbReliable)
  594.         dwFeatures |= 1;
  595.     if (gbIsHost)
  596.         dwFeatures |= 2;
  597.  
  598.     switch (dwFeatures)
  599.     {
  600.     case 0:
  601.         iStringID = IDS_DUEL_TITLE;
  602.         break;
  603.     case 1:
  604.         iStringID = IDS_DUEL_RELIABLE_TITLE;
  605.         break;
  606.     case 2:
  607.         iStringID = IDS_DUEL_HOST_TITLE;
  608.         break;
  609.     case 3:
  610.         iStringID = IDS_DUEL_HOST_RELIABLE_TITLE;
  611.         break;
  612.     }
  613.  
  614.     // get appropriate window title for these features
  615.     LoadString(ghinst, iStringID, tszTitle, MAX_WINDOWTITLE);
  616.     // change window title
  617.     SetWindowText(ghWndMain, tszTitle);               
  618. }
  619.  
  620.  
  621.